#include "degfx/font.h"
#include <assert.h>

static unsigned mx__font_clipped(const MX_RECT * clip, const MX_FONT * font, int x, const int y)
{
	assert(font);

	/* Is it under or over or too far to the right of the clipping rect then
	   we can assume the whole string is clipped */
	if ((y + (int) font->_height < clip->y1) || (y > clip->y2)
		|| (x > clip->x2))
		return true;

	return false;
}

/**font !Draw text onto a bitmap
This function draws text on a bitmap at a specific position using a specified
font and color.  Only the foreground color is drawn, the pixels 'behind' the 
text are not drawn. */
void mx_font_bitmap_draw(const MX_FONT * font, MX_BITMAP * bitmap, const char *text, int len, int x, const int y, const MX_PIXEL fore)
{
	int n = 0;
	const MX__FONT_INDEX *range = 0;

	MX_RECT charrect, clip;

		/** If the font argument is 0 then the default font is used. */
	if (!font)
		font = MXREF(mx__fontref);
	if (!font)
		font = &MX_FONT_DEFAULT;
	assert(font);

	charrect.y1 = y;
	clip = *mx_bitmap_clip_get(bitmap);

	/** If the length argument is less than zero then the string is assumed to be
	    zero terminated */
	if (len < 0)
		len = 0x7fff;

	/** The text drawing is made efficient by skipping text, or portions of
            text that will be clipped. */
	if (mx__font_clipped(&clip, font, x, y))
		return;

	/* Write each character of the string */
	while ((*text) && (n < len)) {
		const unsigned int clen = mx_utf8_len(text);
		const long c = mx_utf8_char(text, clen);

		/* If left side of char farther than right side of clipping, we are
		   done */
		if (x > clip.x2)
			return;

		/* Find the character in the range */
		if ((!range) || (c < range->_start)
			|| (c >= (range->_start + 128)))
			range = mx__font_range(font, c);

		if (range) {
			MX_RECT drawrect;
			const unsigned int width = range->_width[c - range->_start];
			const unsigned char *cdata = &font->_data[range->_index[c - range->_start]];

			charrect.x1 = x;
			charrect.x2 = x + width - 1;
			charrect.y2 = y + font->_height - 1;

			/* Only draw characters that are not completely clipped */
			MXRECT_INTERSECT(charrect, clip, drawrect);
			if (MXRECT_VALID(drawrect))
				font->_drawchar(bitmap, &charrect, &drawrect, cdata, width, fore);

			x = charrect.x2 + 1;
		}

		text += clen;
		++n;
	}
}
